from flask import Flask, request, jsonify
from flask import Flask
from flask import logging
import json
import sys
import os
# 导入bert客户端
from flask_cors import CORS
from termcolor import colored
import configparser

app = Flask(__name__)
# app.debug = True
# 解决中文乱码的问题，将json数据内的中文正常显示
app.config['JSON_AS_ASCII'] = False
# 开启debug模式
app.config['DEBUG'] = True
# flask log
log = logging.create_logger(app)
from semantics import Knowledge
import requests
from util.ThreadPool import threadPool

executor = threadPool.executor

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(str(BASE_DIR))
sys.path.append("..")
# 构建知识点类
knowledge = Knowledge()
from util.RedisUtil import redisClient

rsClient = redisClient.rs

try:
    cf = configparser.ConfigParser()
    cf.read('./config/config.ini', encoding="UTF-8")
    # 获取文件中所有的section(一个配置文件中可以有多个配置，每个section由[]包裹，即[section])，并以列表的形式返回
    secs = cf.sections()
    if len(secs) == 0:
        log.error("配置文件无效!")
        sys.exit(0)
    # 读取配置文件信息到redis
    knowledgesUrl = cf.get("knowledgesUrl", "path")
    rsClient.set("knowledgesUrl", knowledgesUrl)
    fallbackUrl = cf.get("fallbackUrl", "path")
    rsClient.set("fallbackUrl", fallbackUrl)
    # redis
    # redis_host = cf.get("redis", "host")
    # log.info("配置文件解析成功!")
except:
    log.error("配置文件解析失败!")
    sys.exit(0)


# 统一异常处理
@app.errorhandler(Exception)
def special_exception_handler(error):
    log.error(error)
    response = dict(status=500, msg="服务器错误")
    return jsonify(response), 500


# 自定义业务异常
class MyError(Exception):
    # payload 是否变更http status
    def __init__(self, msg, status=None, payload=None):
        Exception.__init__(self)
        self.msg = msg
        self.status = 200
        self.payload = False
        if status is not None:
            self.status = status
        if payload is not None:
            self.payload = payload


@app.errorhandler(MyError)
def MyErrorHandle(error):
    response = dict(status=error.status, msg=error.msg)
    if error.payload is None or error.payload is False:
        return jsonify(response), 200
    else:
        return jsonify(response), error.status


# 语义相似度训练
@app.route('/train', methods=['GET', 'POST'])
def semanticsTrain():
    responseData = {"status": 200, "msg": "成功"}
    # 参数获取
    # getData = request.get_data()
    # list = json.loads(getData).get('questions')
    # password = request.headers.get("password")
    # 参数校验
    # if len(list) == 0 or password is None:
    #     responseData["msg"] = "请求参数不能为空"
    #     responseData["status"] = 400
    #     log.error("addressExtract 请求参数不能为空")
    #     return jsonify(responseData), 400
    taskId = request.json.get("task_id")
    if taskId is None:
        responseData["msg"] = "taskId不能为空"
        responseData["status"] = 400
        log.error("请求参数[taskId]不能为空")
        return jsonify(responseData), 400
    # 取得训练数据
    try:
        rq = requests.get(knowledgesUrl + "?taskId=" + str(taskId), timeout=200)
        if rq.raise_for_status():
            log.error("%s  服务器错误!", knowledgesUrl)
    except:
        log.error("%s 服务未启动!", knowledgesUrl)
    else:
        data = json.loads(rq.text).get("data")
        log.info("训练数据大小：%d", len(data))
        # 异步训练
        executor.submit(knowledge.train, data, taskId)
    msg = '训练中...'
    responseData["data"] = {"msg": msg}
    return jsonify(responseData), 200


# 语义相似度识别
@app.route('/recognise', methods=['POST', "GET"])
def semanticRecognition():
    responseData = {"status": 200, "msg": "成功"}
    # 参数获取
    text = request.args.get("text")
    # 参数校验
    if text is None:
        log.error("addressExtract 请求参数不能为空")
        raise MyError("请求参数不能为空", status=400, payload=True)
    if knowledge.doc_vecs is None:
        raise MyError("暂无模型数据，请先训练！", status=500, payload=True)
    data = knowledge.recognise(text)
    responseData["data"] = data
    return jsonify(responseData), 200


if __name__ == '__main__':
    print('启动中...')
    # app.run(host='10.39.65.192', port=5200)
    app.run(host='0.0.0.0', port=5210)
    print('启动成功')
